/*
 *	Example: linking a program generated with the MS Basic Compiler 
 *	and then converted with the rel2z80 tool to run on the ZX Spectrum.
 *	The BASIC program is linked as if it was a library, and this one
 *	provides the necessary entries, main() included.
 *	This is a sort of "Debugging runtime".. written in C !
 *	There is some inline assembly to read/convert parameters.
 *	Not all the functions are implemented, anyway some simple program 
 *	can be linked and 'run' (or 'debugged' !).
 *
 *
 *	Given a REL file generated by the BASIC Compiler in CP/M, first convert it:
 *	> rel2z80 HILO.REL
 *
 *	This will extract a binary object SSMAIN.O
 *	Now link it into a Z80ASM library and copy the lib in your Z88DK tree:
 *
 *	> z80asm -d -ns -nm -xssmain ssmain.o
 *	> copy ssmain.lib "c:\Program Files\z88dk\lib\clibs"
 *
 *	Ok, this program is the new runtime library.  
 *	Compile it referring to SSMAIN as a library to be included:
 *      > zcc +zxansi -lndos -lssmain -lm -lmalloc -create-app -zorg=26000 baslib.c
 *
 *	Now try "a.tap" on your favourite Spectrum emulator !
 *
 *
 *	$Id: baslib.c,v 1.3 2016-09-17 15:07:16 pauloscustodio Exp $
 *
 */


#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <debug.h>

#include <malloc.h>
#define HPSIZE 2000
HEAPSIZE(HPSIZE)

// Compiled BASIC start address
extern void __LIB__  SSMAIN();

// Begin (initialize runtime env if necessary)
extern void __LIB__  SINI();

// End
extern void __LIB__  SEND();

// Chain - load and run another program.
extern void __LIB__  SCHN();

extern void __LIB__  SRUN();

// Print char
extern void __LIB__  SCHR();

extern void __LIB__  SIN0A();
extern void __LIB__  SIN0B();

extern void __LIB__  SIPUA();
extern void __LIB__  SIPUB();

extern void __LIB__  SLIPA();


extern void __LIB__  SLTMA();
extern void __LIB__  SFMUA();
extern void __LIB__  SFADC();
extern void __LIB__  SGTCC();
extern void __LIB__  SNECE();
extern void __LIB__  SEQCG();
extern void __LIB__  SGTCG();
extern void __LIB__  SEQJG();

// ON GOTO
extern void __LIB__  SOGTA();

// ON GOSUB
//extern void __LIB__  SOGSA();

extern void __LIB__  SCINA();
extern void __LIB__  SCINC();

extern void __LIB__  S530();

// Compare string
extern void __LIB__  SEQTA();

extern void __LIB__  SMID();
extern void __LIB__  SREAA();
extern void __LIB__  SDVDA();
extern void __LIB__  SBSUA();
extern void __LIB__  SSASB();

// LEN string
extern void __LIB__  SLENA();

// Set text width
extern void __LIB__  SWID();

extern void __LIB__  SLFMA();
extern void __LIB__  SFADA();

// float save, put accumulator into specified location
extern void __LIB__  SFASO();
extern void __LIB__  SFASA();

extern void __LIB__  STABA();

extern void __LIB__  SLEF();
extern void __LIB__  SINT();

// RANDOMIZE
extern void __LIB__  SRZ0();
// RND
extern void __LIB__  SRAN();

// Float compare and conditional jump
extern void __LIB__  SLTJA();
extern void __LIB__  SGTJA();
extern void __LIB__  SEQJA();
extern void __LIB__  SNEJA();
extern void __LIB__  SGEJA();
extern void __LIB__  SLEJA();

// Float accumulator compare and conditional jump
extern void __LIB__  SLTJC();
extern void __LIB__  SGTJC();
extern void __LIB__  SEQJC();
extern void __LIB__  SNEJC();
extern void __LIB__  SGEJC();
extern void __LIB__  SLEJC();

extern void __LIB__  SRPT();
extern void __LIB__  SRGT();

extern void __LIB__  SDKN();
extern void __LIB__  SDKM();
extern void __LIB__  SDKC();

extern void __LIB__  SSTMA();

extern void __LIB__  SPV0C();

// Print (no newline)
extern void __LIB__  SPV1A();	// float
extern void __LIB__  SPV1B();	// double precision
extern void __LIB__  SPV1C();	// integer
extern void __LIB__  SPV1D();	// string
// Print (newline)
extern void __LIB__  SPV2A();	// float
extern void __LIB__  SPV2B();	// double precision
extern void __LIB__  SPV2C();	// integer
extern void __LIB__  SPV2D();	// string

extern void __LIB__  SCISA();
extern void __LIB__  SIMUG();
extern void __LIB__  SFMUC();
extern void __LIB__  SFMUE();
extern void __LIB__  SPR0A();
extern void __LIB__  SPR0D();

extern void DOJUMP();

void	*tmem;

#asm
; MS BASIC FP accumulator

	PUBLIC	SAC
.SAC
	defb	0,0,0,0
#endasm


int	B_CHAN = 0;
char	B_FLAGS = ' ';
int	B_RECSIZ = 0;
int	B_TMPINT = 0;
int	B_TMPINT2 = 0;
int	B_TMPINT3 = 0;
float	B_TMPFLOAT;
float	B_TMPFLOAT2;
char	B_TMPSTR [255];
char	B_TMPSTR2 [255];


#ifdef DEBUG
void pause()
{
	int i;
	for (i=0; i<2000; i++)
	  printf("");
}
#endif


void SINI()
{
	#asm
	push	hl
	#endasm

#ifdef DEBUG
	printf("Initializing...\n");
	pause ();
#endif

	heapinit(HPSIZE);
	}


// Chain
void SCHN()
{
	#asm
	call	readstr
	#endasm
#ifdef DEBUG
	printf("SCHN.- LOAD AND RUN ANOTHER PROGRAM: '%s'\n", B_TMPSTR);
	pause ();
#endif
	exit(0);
	}


void SEND()
{
#ifdef DEBUG
	printf("Exiting...\n");
	pause ();
#endif
	exit(0);
	}


void SRUN()
{
#ifdef DEBUG
	printf("SRUN\n");
	pause ();
#endif
	}


void SCHR()
{
	#asm
	ld	(_B_TMPINT),hl
	jr nocls
	ld	a,26
	cp	l
	jr	nz,nocls
	ld	l,12
nocls:
	ld	(mychr),hl
	#endasm

#ifdef DEBUG
	printf("SCHR - print char %u\n",B_TMPINT);
	pause ();
#endif

	#asm
	ld	hl,chrstr
	ret

chrstr:
	defb	1
	defw	mychr
mychr:
	defb	65 
	#endasm

	}


void SLTMA()
{
#ifdef DEBUG
	printf("SLTMA\n");
	pause ();
#endif
	}


void SFMUA()
{
	#asm
	call	read2parms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	de,_B_TMPFLOAT2
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SFMUA - variable (%u){%f} and (%u){%f} \n", B_TMPINT, B_TMPFLOAT, B_TMPINT2, B_TMPFLOAT2);
	pause ();
#endif
	}


void SFADC()
{
	#asm
	call	read1parm
	ld	hl,_B_TMPFLOAT
	call	store_float
	
	ld	(_B_TMPINT),hl
	ld	de,_B_TMPFLOAT
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SFADC - variable (%u){%f}\n", B_TMPINT, B_TMPFLOAT);
	pause ();
#endif
	}


// ???
void SGTCC()
{
	#asm
	call	read1parm
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SGTCC - expr (SAC > (%u){%f})\n", B_TMPINT, B_TMPFLOAT);
	pause ();
#endif
	}

void SNECE()
{
#ifdef DEBUG
	printf("SNECE\n");
	pause ();
#endif
	}


void SEQCG()
{
	#asm
	call	read1parm
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SEQCG - (%u)%f \n", B_TMPINT, B_TMPFLOAT);
	pause ();
#endif
	}


// ???
void SGTCG()
{
	#asm
	call	read1parm
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SGTCG - expr (SAC > (%u){%f})\n", B_TMPINT, B_TMPFLOAT);
	pause ();
#endif
	}


void SEQJG()
{
#ifdef DEBUG
	printf("SEQJG\n");
	pause ();
#endif
	}


// ON GOTO
void SOGTA()
{
#asm
	ld	(_B_TMPINT),hl
	
	ld	a,l
	pop	hl
	ld	b,(hl)
	inc	hl
	push	hl
	and	a
	jr	z,zogt

	;cp	1	; default ??
	;jr	z,zogt
	
	inc	b
	cp	b
	jr	nc,zogt

	push	af
	push	bc
;#endasm
;	
;#ifdef DEBUG
;	printf("SOGTA - ON %u GOTO\n", B_TMPINT);
;	pause ();
;#endif
;
;#asm
;	pop	af
;	pop	bc
	
	pop	hl
sogt:
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	dec	a
	jr	nz,sogt
	push	de
	ret
	
zogt:
	pop	hl
	dec	b
noogt:
	inc	hl
	inc	hl
	djnz	noogt
	push	hl

#endasm

#ifdef DEBUG
	printf("SOGTA - ON GOTO, value %u doesn't match\n", B_TMPINT);
	pause ();
#endif
	}


void SCINA()
{
	#asm
	ld	(_B_TMPINT),hl
	ld	de,_B_TMPFLOAT
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SCINA - pick %f (%u) and keep its int {%u}\n", B_TMPFLOAT, B_TMPINT, (int)B_TMPFLOAT);
	pause ();
#endif
	B_TMPINT=(int)B_TMPFLOAT;
	
	#asm
	ld	hl,(_B_TMPINT)
	#endasm
	
	}


void SCINC()
{
	printf("SCINC\n");
}


void S530()
{
#ifdef DEBUG
	printf("S530\n");
	pause ();
#endif
	}


void SMID()
{
	#asm
	call	readstr
	#endasm

	printf("SMID - '%s'\n", B_TMPSTR);
}


void SLENA()
{
	#asm
	call	readstr
	#endasm

#ifdef DEBUG
	printf("SLENA - LEN('%s')=%u\n", B_TMPSTR, strlen(B_TMPSTR));
#endif

	B_TMPINT=strlen(B_TMPSTR);
	
}


void SREAA()
{
	printf("SREAA\n");
}


void SDVDA()
{
	#asm
	call	read2parms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	de,_B_TMPFLOAT2
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SDVDA - %f(%u) / %f(%u)\n", B_TMPFLOAT, B_TMPINT, B_TMPFLOAT2, B_TMPINT2);
#endif
	
	B_TMPFLOAT=B_TMPFLOAT/B_TMPFLOAT2;
	
	#asm
	ld	hl,_B_TMPFLOAT
	ld	de,SAC
	call	store_float
	#endasm
}


void SBSUA()
{
	printf("SBSUA\n");
}



void SSASB()
{
	#asm
	ld	(_B_TMPINT),hl
	#endasm
	
	printf("SSASB - $u\n", B_TMPINT);
}


void SEQTA()
{
	
	#asm
	call	read2str
	call	readjpparm
	#endasm

#ifdef DEBUG
	printf("SEQTA - Compare string '%s' with '%s'(%u), if eq jp to %u\n", B_TMPSTR, B_TMPSTR2, B_TMPINT2, B_TMPINT);
	//printf("Result: %s\n",(strcmp ((char *)B_TMPSTR, (char *)B_TMPSTR2) == 0));
	pause ();
#endif

#asm
	ld	hl,_B_TMPSTR
	ld	de,_B_TMPSTR2
.strcmp1
        ld      a,(de)	; Next char from s2
        inc	de	; Ready for next char
        cpi     	; Compare with s1 (and inc hl) -- does not set C flag
        ret	nz	; Different!
        and     a	; Check for end of strings
        jr      nz,strcmp1 ; Round again
; Both strings ended simultaneously 
; now we know *s1=*s2=0, return hl=0
	call	_DOJUMP
#endasm

	}


void SWID()
{
#ifdef DEBUG
	#asm
	ld	(_B_TMPINT),hl
	#endasm
	
	printf("SWID - Set screen text width to %u\n", B_TMPINT);
	pause ();
#endif
	}


void SLFMA()
{
	#asm
	call	read1parm
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	#endasm
	
#ifdef DEBUG
	printf("SLFMA - load float constant %f\n", B_TMPFLOAT);
#endif
	
	#asm
	ld	hl,_B_TMPFLOAT
	ld	de,SAC
	call	store_float
	#endasm

#ifdef DEBUG
	pause ();
#endif
	}


void SFADA()
{
	#asm
	call	read2parms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	de,_B_TMPFLOAT2
	call	load_float
	#endasm
	
#ifdef DEBUG
	printf("SFADA - %f (%u) + %f (%u) = %f\n", B_TMPFLOAT, B_TMPINT, B_TMPFLOAT2, B_TMPINT2, B_TMPFLOAT+B_TMPFLOAT2);
#endif
	
	B_TMPFLOAT = B_TMPFLOAT+B_TMPFLOAT2;
	#asm
	ld	hl,_B_TMPFLOAT
	ld	de,SAC
	call	store_float
	#endasm

#ifdef DEBUG
	pause ();
#endif
	}


void SFASO()
{
	#asm
	call	read1parm
	ld	hl,SAC
	ld	bc,4
	ldir
	#endasm
	
#ifdef DEBUG
	#asm
	ld	hl,(_B_TMPINT)
	ld	de,(_B_TMPFLOAT)
	call	load_float
	#endasm
	
	printf("SFASO - put result {%f} in (%u)\n", B_TMPFLOAT, B_TMPINT);
	pause ();
#endif

	}


void SFASA()
{
	// I'm unsure.. perhaps I should malloc 4 bytes and update value as a ptr to it ?
	#asm
	call	read2parms
	ld	hl,(_B_TMPINT2)
	ld	de,(_B_TMPINT)
	ld	bc,4
	ldir
	#endasm
	
#ifdef DEBUG
	#asm
	ld	hl,(_B_TMPINT2)
	ld	de,(_B_TMPFLOAT2)
	call	load_float
	#endasm

	printf("SFASA - (%u) = %f\n", B_TMPINT, B_TMPFLOAT2);
	pause ();
#endif
	}


void STABA()
{
	#asm
	ld	(_B_TMPINT),hl
	#endasm

#ifdef DEBUG
	printf("STABA - Print TAB %u \n", B_TMPINT);
	pause ();
#else
	for ( B_TMPINT2=0; B_TMPINT2<B_TMPINT; B_TMPINT2++)
	    printf(" ");
#endif
	}


void SLEF()
{
	#asm
	ld	(_B_TMPINT),hl
	ld	(_B_TMPINT2),de
	;;ld	a,l
	;;ld	(de),a
	#endasm

#ifdef DEBUG
	printf("SLEF - Left (string in %u),%u\n", B_TMPINT2, B_TMPINT);
	pause ();
#endif
	}


void SINT()
{
	#asm
	ld	hl,SAC
	ld	de,_B_TMPFLOAT
	call	load_float
	#endasm

	B_TMPINT = (int) B_TMPFLOAT;

#ifdef DEBUG
	printf("SINT - %f; result: %u\n", B_TMPFLOAT, B_TMPINT);
#endif

	B_TMPFLOAT = (float) B_TMPINT;
	#asm
	ld	hl,_B_TMPFLOAT
	ld	de,SAC
	call	store_float
	#endasm
	
#ifdef DEBUG
	pause ();
#endif
	}


void SRZ0()
{
#ifdef DEBUG
	printf("SRZ0 - RANDOMIZE\n");
	pause ();
#endif
	//srand(0);
	}


void SRAN()
{
	#asm
	ld	(_B_TMPINT),hl
	#endasm

	B_TMPFLOAT = (rand() / RAND_MAX.0) * (float) B_TMPINT;

#ifdef DEBUG
	printf("SRAN - RND(%u); got: %f\n", B_TMPINT, B_TMPFLOAT);
#endif

	//B_TMPFLOAT = -259.5;

	#asm
	ld	hl,_B_TMPFLOAT
	ld	de,SAC
	call	store_float
	#endasm
	
	
	#asm
	ld	hl,SAC
	ld	de,_B_TMPFLOAT
	call	load_float
	#endasm
	
#ifdef DEBUG
	printf ("Float stored: %f\n", B_TMPFLOAT);
	pause ();
#endif
	}


void SLTJA()
{
	#asm
	call	read3jpparms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	de,_B_TMPFLOAT2
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SLTJA - if %f (%u) < %f (%u) jump to %u \n", B_TMPFLOAT, B_TMPINT, B_TMPFLOAT2, B_TMPINT2, B_TMPINT3);
	pause ();
#endif
	if (B_TMPFLOAT < B_TMPFLOAT2)
	  DOJUMP();
	}


void SGTJA()
{
	#asm
	call	read3jpparms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	de,_B_TMPFLOAT2
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SGTJA - if %f (%u) > %f (%u) jump to %u \n", B_TMPFLOAT, B_TMPINT, B_TMPFLOAT2, B_TMPINT2, B_TMPINT3);
	pause ();
#endif
	if (B_TMPFLOAT > B_TMPFLOAT2)
	  DOJUMP();
	}


void SEQJA()
{
	#asm
	call	read3jpparms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	de,_B_TMPFLOAT2
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SEQJA - if %f (%u) = %f (%u) jump to %u \n", B_TMPFLOAT, B_TMPINT, B_TMPFLOAT2, B_TMPINT2, B_TMPINT3);
	pause ();
#endif
	if (B_TMPFLOAT == B_TMPFLOAT2)
	  DOJUMP();
	}


void SNEJA()
{
	#asm
	call	read3jpparms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	de,_B_TMPFLOAT2
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SEQJA - if %f (%u) <> %f (%u) jump to %u \n", B_TMPFLOAT, B_TMPINT, B_TMPFLOAT2, B_TMPINT2, B_TMPINT3);
	pause ();
#endif
	if (B_TMPFLOAT != B_TMPFLOAT2)
	  DOJUMP();
	}


void SGEJA()
{
	#asm
	call	read3jpparms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	de,_B_TMPFLOAT2
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SLEJA - if %f (%u) >= %f (%u) jump to %u \n", B_TMPFLOAT, B_TMPINT, B_TMPFLOAT2, B_TMPINT2, B_TMPINT3);
	pause ();
#endif
	if (!(B_TMPFLOAT < B_TMPFLOAT2))
	  DOJUMP();
	}


void SLEJA()
{
	#asm
	call	read3jpparms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	de,_B_TMPFLOAT2
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SLEJA - if %f (%u) <= %f (%u) jump to %u \n", B_TMPFLOAT, B_TMPINT, B_TMPFLOAT2, B_TMPINT2, B_TMPINT3);
	pause ();
#endif
	if (!(B_TMPFLOAT > B_TMPFLOAT2))
	  DOJUMP();
	}


void SLTJC()
{
	#asm
	call	read2parms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	(jploc +1 ),hl
	#endasm

#ifdef DEBUG
	printf("SLTJC - if SAC < (%u) {%f} jp %u\n", B_TMPINT, B_TMPFLOAT, B_TMPINT2);
	pause ();
#endif
	if (B_TMPFLOAT < B_TMPFLOAT2)
	  DOJUMP();
	}


void SGTJC()
{
	#asm
	call	read2parms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	(jploc +1 ),hl
	#endasm

#ifdef DEBUG
	printf("SGTJC - if SAC > (%u) {%f} jp %u\n", B_TMPINT, B_TMPFLOAT, B_TMPINT2);
	pause ();
#endif
	if (B_TMPFLOAT > B_TMPFLOAT2)
	  DOJUMP();
	}


void SEQJC()
{
	#asm
	call	read2parms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	(jploc +1 ),hl
	#endasm

#ifdef DEBUG
	printf("SEQJC - if SAC = (%u) {%f} jp %u\n", B_TMPINT, B_TMPFLOAT, B_TMPINT2);
	pause ();
#endif
	if (B_TMPFLOAT == B_TMPFLOAT2)
	  DOJUMP();
	}


void SNEJC()
{
	#asm
	call	read2parms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	(jploc +1 ),hl
	#endasm

#ifdef DEBUG
	printf("SNEJC - if SAC <> (%u) {%f} jp %u\n", B_TMPINT, B_TMPFLOAT, B_TMPINT2);
	pause ();
#endif
	if (B_TMPFLOAT != B_TMPFLOAT2)
	  DOJUMP();
	}


void SGEJC()
{
	#asm
	call	read2parms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	(jploc +1 ),hl
	#endasm

#ifdef DEBUG
	printf("SGEJC - if SAC >= (%u) {%f} jp %u\n", B_TMPINT, B_TMPFLOAT, B_TMPINT2);
	pause ();
#endif
	if (!(B_TMPFLOAT < B_TMPFLOAT2))
	  DOJUMP();
	}


void SLEJC()
{
	#asm
	call	read2parms
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float
	ld	hl,(_B_TMPINT2)
	ld	(jploc +1 ),hl
	#endasm

#ifdef DEBUG
	printf("SLEJC - if SAC <= (%u) {%f} jp %u\n", B_TMPINT, B_TMPFLOAT, B_TMPINT2);
	pause ();
#endif
	if (!(B_TMPFLOAT > B_TMPFLOAT2))
	  DOJUMP();
	}


void SRPT()
{
	#asm
	ld	(_B_CHAN),de
	ld	(_B_TMPINT),hl
	#endasm

#ifdef DEBUG
	printf("SRPT - put to stream #%u value.. %u \n", B_CHAN, B_TMPINT);
	pause ();
#endif
	}

void SRGT()
{
	#asm
	ld	(_B_CHAN),de
	ld	(_B_TMPINT),hl
	#endasm

#ifdef DEBUG
	printf("SRGT - get from stream #%u value.. %u \n", B_CHAN, B_TMPINT);
	pause ();
#endif
	}


void SDKN()
{
	#asm
	call	readstr
	#endasm
	
	B_FLAGS = B_TMPSTR[0];

#ifdef DEBUG
	printf("SDKN - Init OPEN with flags: '%s'\n", B_TMPSTR);
	pause ();
#endif
	}


void SDKM()
{
	#asm
	ld	(_B_CHAN),bc
	ld	(_B_RECSIZ),hl
	ld	h,d
	ld	l,e
	call	readstr
	#endasm

#ifdef DEBUG
	printf("SDKM - open '%c', %u, '%s', recsize %u \n", B_FLAGS, B_CHAN, B_TMPSTR, B_RECSIZ);
	pause ();
#endif
	}


void SDKC()
{
	#asm
	ld	(_B_TMPINT),hl
	#endasm

#ifdef DEBUG
	printf("SDKC - close #%u\n", B_TMPINT);
	pause ();
#endif
	}


void SSTMA()
{
#ifdef DEBUG
	printf("SSTMA\n");
	pause ();
#endif
	}


void SIN0A()
{
	#asm
	call	readstr
	pop	hl
	ld	e,(hl)
	inc	hl
	ld	d,0
	ld	(_B_TMPINT),de
	push	hl
	#endasm

#ifdef DEBUG
	printf("SIN0A - Print msg for input: '%s' - flag %u\n", B_TMPSTR, B_TMPINT);
	pause ();
#else
	printf("%s ?  ", B_TMPSTR);
#endif
	}


void SIN0B()
{
	#asm
	ld	(_B_TMPINT),hl
	#endasm

#ifdef DEBUG
	printf("SIN0B - set up input from #%u\n", B_TMPINT);
	pause ();
#endif
	}


void SLIPA()
{
	#asm
	ld	(_B_TMPINT),hl
	push	hl
	#endasm

#ifdef DEBUG
	printf("SLIPA - line input: put string in location %u\n", B_TMPSTR);
	pause ();
#endif	
	gets (B_TMPSTR);

	#asm
	pop	hl
	#endasm
	}


void SIPUA()
{
	#asm
	call	read1parm
	#endasm
	
	// 10100000001 -- 1281 -- Number   ( byte sequence: 01 07 )
	// 11100000001 -- 1793 -- string   ( byte sequence: 01 05 )

	gets (B_TMPSTR);
	if (!(B_TMPINT & 512))
	{
		B_TMPFLOAT = atof(B_TMPSTR);
#ifdef DEBUG
		printf ("  SIPUA - %f",B_TMPFLOAT);
#endif
	}
	printf ("\n");

#ifdef DEBUG
	pause ();
#endif
	}


void SIPUB()
{
	#asm
	ld	(_B_TMPINT2),hl
	ld	d,h
	ld	e,l
	ld	a,(_B_TMPINT+1)
	and	2
	jr	nz,is_string
	ld	hl,_B_TMPFLOAT
	call	store_float
	;jr	is_num
.is_string
	;ld	hl,_B_TMPSTR
	;call	store_string
	;.is_num
	#endasm

	if (B_TMPINT & 512)
	{
		tmem=malloc(strlen(B_TMPSTR)+3);
		
#ifdef DEBUG
		printf ("\n Malloc of %u bytes; location %u\n", strlen(B_TMPSTR)+3, tmem);
#endif
		
		#asm
		ld	hl,_B_TMPSTR
		ld	de,(_tmem)
		call	store_string
		
		; copy the string ptr onto the variable position
		ld	hl,(_tmem)
		ld	de,(_B_TMPINT2)
		ld	bc,3
		ldir
		#endasm

#ifdef DEBUG
		printf ("\n .entered string %s\n", B_TMPSTR);
#endif
	}
	else
	{
		#asm
		;ld	de,(_B_TMPINT2)
		;call	store_float
		ld	hl,(_B_TMPINT2)
		ld	de,_B_TMPFLOAT
		call	load_float
		#endasm
#ifdef DEBUG
		printf ("\n...entered number %f\n", B_TMPFLOAT);
#endif
	}

#ifdef DEBUG
	printf("SIPUB - string ptr now points to %u\n", B_TMPINT2);
	pause ();
#endif
	}


void SPV0C()
{
#ifdef DEBUG
	printf("SPV0C\n");
	pause ();
#endif
	}


void SPV1A()
{
	#asm
	ld	(_B_TMPINT),hl
	ld	de,_B_TMPFLOAT
	call	load_float
	#endasm
	
#ifdef DEBUG
	printf("SPV1A - (%u) ", B_TMPINT);
#endif
	printf(" %f ", B_TMPFLOAT);

#ifdef DEBUG
	printf("\n");
	pause ();
#endif
	}


void SPV1B()
{
	#asm
	ld	(_B_TMPINT),hl
	ld	de,_B_TMPFLOAT
	call	load_double
	#endasm
	
#ifdef DEBUG
	printf("SPV1B - (%u) ", B_TMPINT);
#endif
	printf(" %f ", B_TMPFLOAT);

#ifdef DEBUG
	printf("\n");
	pause ();
#endif
	}


void SPV1C()
{
	#asm
	ld	h,d
	ld	l,e
	ld	(_B_TMPINT),hl
	#endasm
	
#ifdef DEBUG
	printf("SPV1C - ");
#endif

	printf(" %u ", B_TMPINT);

#ifdef DEBUG
	printf("\n");
	pause ();
#endif
	}


void SPV1D()
{
	#asm
	call	readstr
	#endasm

#ifdef DEBUG
	printf("SPV1D - ");
#endif

	printf("%s", B_TMPSTR);

#ifdef DEBUG
	printf("\n");
	pause ();
#endif
	}


void SPV2A()
{
	#asm
	ld	(_B_TMPINT),hl
	ld	de,_B_TMPFLOAT
	call	load_float
	#endasm
	
#ifdef DEBUG
	printf("SPV2A - (%u) ", B_TMPINT);
#endif
	printf(" %f\n", B_TMPFLOAT);

#ifdef DEBUG
	pause ();
#endif
	}


void SPV2B()
{
	#asm
	ld	(_B_TMPINT),hl
	ld	de,_B_TMPFLOAT
	call	load_double
	#endasm
	
#ifdef DEBUG
	printf("SPV2B - (%u) ", B_TMPINT);
#endif
	printf(" %f\n", B_TMPFLOAT);

#ifdef DEBUG
	pause ();
#endif
	}


void SPV2C()
{
	#asm
	ld	h,d
	ld	l,e
	ld	(_B_TMPINT),hl
	#endasm
	
#ifdef DEBUG
	printf("SPV2C - ");
#endif

	printf(" %u\n", B_TMPINT);

#ifdef DEBUG
	pause ();
#endif
	}


void SPV2D()
{
	#asm
	call	readstr
	#endasm

#ifdef DEBUG
	printf("SPV2D - ");
#endif

	printf("%s\n", B_TMPSTR);

#ifdef DEBUG
	pause ();
#endif
	}


void SCISA()
{
	#asm
	ld	(_B_TMPINT),hl
	#endasm

#ifdef DEBUG
	printf("SCISA - put int {%u} into float SAC\n", B_TMPINT);
	pause ();
#endif
	B_TMPFLOAT = (float) B_TMPINT;

	#asm
	ld	hl,_B_TMPFLOAT
	ld	de,SAC
	call	store_float
	#endasm
	}


void SIMUG()
{
	#asm
	ld	(_B_TMPINT),hl
	#endasm
	
#ifdef DEBUG
	printf("SIMUG - (INTEGER multiply * %u)\n", B_TMPINT);
	pause ();
#endif
	}


void SIMUC()
{
	#asm
	ld	(_B_TMPINT),hl
	#endasm
	
#ifdef DEBUG
	printf("SIMUC - (INTEGER multiply * %u)\n", B_TMPINT);
	pause ();
#endif
	}


void SIMUE()
{
	#asm
	ld	(_B_TMPINT),hl
	#endasm
	
#ifdef DEBUG
	printf("SIMUE - (INTEGER multiply * %u)\n", B_TMPINT);
	pause ();
#endif
	}


void SFMUC()
{
	#asm
	call	read1parm
	ld	hl,(_B_TMPINT)
	ld	de,_B_TMPFLOAT
	call	load_float

	ld	hl,SAC
	ld	de,_B_TMPFLOAT2
	call	load_float
	#endasm

#ifdef DEBUG
	printf("SFMUC - (FLOAT multiply %f * %f)\n", B_TMPFLOAT2, B_TMPFLOAT);
#endif

	B_TMPFLOAT = B_TMPFLOAT * B_TMPFLOAT2;

	#asm
	ld	hl,_B_TMPFLOAT
	ld	de,SAC
	call	store_float
	#endasm
	
#ifdef DEBUG
	pause ();
#endif
	}


void SFMUE()
{
#ifdef DEBUG
	printf("SFMUE - (FLOAT multiply ?)\n");
	pause ();
#endif
	}


void SPR0A()
{
// Probably this had to print a "Line feed"

#ifdef DEBUG
	printf("* ");
#endif
	}


void SPR0D()
{
	#asm
	ld	(_B_TMPINT),hl
	ld	h,d
	ld	l,e
	call	readstr
	#endasm
	
#ifdef DEBUG
	printf("SPR0D - Setup print to #%u: %s[CR]\n", B_TMPINT, B_TMPSTR);
	pause ();
#endif
	}


// Main entry - just links the "library" with the BASIC compiled object code
main()
{
	SSMAIN();
	}



// Service routines: 
// transfer and convert data from/to program memory or data areas

#asm


.readstr
	ld	c,(hl)
	inc	hl
	ld	a,(hl)
	inc	hl
	ld	h,(hl)
	ld	l,a
	ld	de,_B_TMPSTR
	ld	b,0
	inc	bc
	ldir
	dec	de
	xor	a
	ld	(de),a
	ret


.read2str
	push	de
	ld	c,(hl)
	inc	hl
	ld	a,(hl)
	inc	hl
	ld	h,(hl)
	ld	l,a
	ld	de,_B_TMPSTR
	ld	b,0
	inc	bc
	ldir
	dec	de
	xor	a
	ld	(de),a
	pop	de
	ld	h,d
	ld	l,e
	ld	c,(hl)
	inc	hl
	ld	a,(hl)
	inc	hl
	ld	h,(hl)
	ld	l,a
	ld	de,_B_TMPSTR2
	ld	b,0
	inc	bc
	ldir
	dec	de
	xor	a
	ld	(de),a
	ret

.readjpparm
	pop	bc
	pop	hl
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	(_B_TMPINT),de
	ld	(jploc + 1),de
	push	hl
	push	bc
	ret


.read3jpparms
	pop	bc
	pop	hl
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	(_B_TMPINT),de
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	(_B_TMPINT2),de
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	(_B_TMPINT3),de
	ld	(jploc + 1),de
	push	hl
	push	bc
	ret


.read2parms
	pop	bc
	pop	hl
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	(_B_TMPINT),de
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	(_B_TMPINT2),de
	push	hl
	push	bc
	ret


.read1byte2parms
	pop	bc
	pop	hl
	ld	d,0
	inc	hl
	ld	e,(hl)
	ld	(_B_TMPINT3),de
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	(_B_TMPINT),de
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	(_B_TMPINT2),de
	push	hl
	push	bc
	ret


.read1parm
	pop	bc
	pop	hl
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	push	hl
	push	bc
	ld	(_B_TMPINT),de
	ret


; Pick float in HL (MS Basic format) and put it into DE (Z88DK format)

.load_float
	xor	a
	ld	(de),a
	inc	de
	ld	(de),a
	inc	de
	ld	bc,4
	ldir	
	ret


; Pick double precision # in HL (MS Basic format) and put it into DE (Z88DK format)

.load_double
	inc	hl
	inc	hl
	ld	bc,6
	ldir
	ret


; Move float in HL (Z88DK format) to DE (MS Basic format)

.store_float
	ld	bc,4
	inc	hl
	inc	hl
	ldir
	ret


; Move # in HL (Z88DK format) to DE (MS Basic format) in double precision 

.store_double
	ld	bc,6
	;xor	a	; we leave the extra precision bytes untouched:
	;ld	(de),a  ; no need to force them to zero because no one will use them
	inc	de
	;ld	(de),a
	inc	de
	ldir
	ret


; Copy C style string in HL to DE in BASIC format.
; The first byte holds the string lenght, then we have two bytes
; for the string location and the string itself (non terminated).

.store_string
	push	hl
	ld	bc,0
.count_loop
	ld	a,(hl)
	and	a
	jr	z,end_count
	inc	hl
	inc	c
	jr	nz,count_loop
.end_count
	ld	h,d
	ld	l,e
	ld	(hl),c
	inc	hl
	inc	de
	inc	de
	inc	de
	ld	(hl),e
	inc	hl
	ld	(hl),d
	pop	hl
	ldir
	
	ret


._DOJUMP
;	pop	hl
	pop	hl
.jploc  jp	jploc


#endasm

